/**
 * @file	i2c_slave.c
 * @author	chipsea
 * @brief	
 * @version	0.1
 * @date	2020-11-30
 * @copyright Copyright (c) 2020, CHIPSEA Co., Ltd.
 * @note
 */

/*******************************************************************************
* @file		i2c_slave.c
* @brief	i2c slave function
* @version	1.0

*******************************************************************************/

/*******************************************************************************
*@ Module    	  	:  Includes
*@ Description    :  NULL
*******************************************************************************/
#include "i2c_slave.h"
#include "gpio.h"
#include "error.h"
#include "osal.h"
#include "clock.h"
#include "log.h"

/*******************************************************************************
*@ Module    	  	:  IIC_Slave status
*@ Description    :  NULL
*******************************************************************************/
typedef enum
{
	Slave_Closed = 0,
	Slave_Opened,
}IIC_Slave_status;

/*******************************************************************************
*@ Module    	  	:  IIC_Slave_cfg structure
*@ Description    :  NULL
*******************************************************************************/
typedef struct
{
	AP_I2C_TypeDef 		*addr;									// get by software
	per_module_t 					module;									// get by software
	uint8_t 					INTR_ID;								// get by software
	GpioPin_t 				SDA_PIN;								// I2C Pin 
	GpioPin_t 				SCL_PIN;
	Fmux_Type_e				Fmux_SCL;								// get by software
	Fmux_Type_e				Fmux_SDA;								// get by software
	IIC_Slave_status 	state;
}IIC_Slave_cfg;

/*******************************************************************************
*@ Module    	  	:  Global Variable
*@ Description    :  NULL
*******************************************************************************/
 IIC_Slave_cfg Slave_cfg_g[IIC_COUNT];

/*******************************************************************************
*@ Module    	  	:  Internal Function statement
*@ Description    :  NULL
*******************************************************************************/
void I2C_Slave_Handler(I2C_Evt_t *pev);

/*******************************************************************************
*@ Module    	  	:  Function Statement
*@ Description    :  NULL
*******************************************************************************/
uint8_t Hal_I2C_Slave_Init(I2C_Slave_Parameter *para,uint8_t *handle)
{
	uint8_t ret;
	LOG("Hal_I2C_Slave_Init wakeup id:%02X \r\n",para->id);
	ret = Hal_IIC_Valid_Check(para->id);
	if( ret == TRUE )
	{
		return ERR_IIC_BUSY;
	}
	else if( ret == ERR_IIC_ID)
	{
		return ERR_IIC_ID;
	}
	else
	{
		if( Hal_IIC_Addr_Valid(para->Slave_Address) !=  IIC_SUCCESS)
			return ERR_IIC_ADDRESS;
		
		osal_memset(&Slave_cfg_g[para->id],0,sizeof(IIC_Slave_cfg));
		
		// pre-para get
		Slave_cfg_g[para->id].addr = Hal_Get_IIC_Instance(para->id);
		Slave_cfg_g[para->id].module = Hal_GetIIC_ModuleID(para->id);
		Slave_cfg_g[para->id].INTR_ID = Hal_GetIIC_IRQID(para->id);
		Hal_GetIIC_PIN_Fmux(para->id,&(Slave_cfg_g[para->id].Fmux_SCL),&(Slave_cfg_g[para->id].Fmux_SDA));
		Slave_cfg_g[para->id].state = Slave_Closed;
		
		// io init
		Slave_cfg_g[para->id].SCL_PIN = para->SCL_PIN;
		Slave_cfg_g[para->id].SDA_PIN = para->SDA_PIN;
		HalGpioFmuxConfig(para->SCL_PIN, Slave_cfg_g[para->id].Fmux_SCL);
		HalGpioFmuxConfig(para->SDA_PIN, Slave_cfg_g[para->id].Fmux_SDA);
		HalGpioPupdConfig(para->SCL_PIN,STRONG_PULL_UP);
		HalGpioPupdConfig(para->SDA_PIN,STRONG_PULL_UP);
		
		// init
		hal_clk_gate_enable(Slave_cfg_g[para->id].module);
		
		Slave_cfg_g[para->id].addr->IC_ENABLE = FALSE;
		Slave_cfg_g[para->id].addr->IC_CON = para->workmode | para->AddressMode; 
		Slave_cfg_g[para->id].addr->IC_SAR = para->Slave_Address;
		Slave_cfg_g[para->id].addr->IC_RX_TL = para->RX_FIFO_Len - 1;
		Slave_cfg_g[para->id].addr->IC_TX_TL = para->Tx_FIFO_Len - 1;
		Slave_cfg_g[para->id].addr->IC_INTR_MASK = para->IRQ_Source;
	
		Hal_IIC_Register_CallBack(para->id,para->evt_handler);
		
		Hal_I2c_Slave_Open(para->id);
		// NVIC Config
		NVIC_EnableIRQ((IRQn_Type)(Slave_cfg_g[para->id].INTR_ID));
		
		NVIC_SetPriority((IRQn_Type)(Slave_cfg_g[para->id].INTR_ID), IRQ_PRIO_HAL);

		*handle = para->id;
		return IIC_SUCCESS;
	}
}

/*******************************************************************************
*@ Module    	  	:  Open I2C Slave
*@ Description    :  NULL
*******************************************************************************/
uint8_t Hal_I2c_Slave_Open(uint8_t handle)
{
	if( Slave_cfg_g[handle].state == Slave_Closed )
	{
		Slave_cfg_g[handle].state = Slave_Opened;
		Slave_cfg_g[handle].addr->IC_ENABLE = TRUE;
		return IIC_SUCCESS;
	}
	else
		return ERR_IIC_FAILURE;
}

/*******************************************************************************
*@ Module    	  	:  Close I2C Slave
*@ Description    :  NULL
*******************************************************************************/
void Hal_I2c_Slave_Close(uint8_t handle)
{
	Slave_cfg_g[handle].addr->IC_ENABLE = FALSE;
}

/*******************************************************************************
*@ Module    	  	:  Close I2C Slave
*@ Description    :  Should check close states,if closed completed
										 a delay occurs when IC_ENABLE is set to 0, because close iic module depends
										 on the iic bus activity
*******************************************************************************/
uint8_t Hal_Check_I2C_Slave_Closed(uint8_t handle)
{
	if( Hal_Check_IIC_Closed(Slave_cfg_g[handle].addr) == IIC_SUCCESS )
	{
		Slave_cfg_g[handle].state = Slave_Closed;
		return IIC_SUCCESS;
	}
	else
		return ERR_IIC_ENABLE;
}

/*******************************************************************************
*@ Module    	  	:  Close I2C Slave
*@ Description    :  NULL
*******************************************************************************/
uint8_t Hal_I2C_Slave_Deinit(uint8_t *handle)
{
	LOG("HAL I2C SLAVE DINIT handle Value %d \n",*handle);
	if( Hal_IIC_unRegister_CallBack(*handle) != IIC_SUCCESS )
		return ERR_IIC_FAILURE;
	
	*handle = INVALID_HANDLE;
	return IIC_SUCCESS;
}

/*******************************************************************************
*@ Module    	  	:  Read data from rx fifo
*@ Description    :  NULL
*******************************************************************************/
void Hal_I2C_Slave_ReadRX_FIFO(uint8_t handle,uint8_t *p,uint8_t len)
{
	for(uint8_t i =0;i<len;i++)
		*p++ = Hal_IIC_Read_RXFIFO(Slave_cfg_g[handle].addr);
}

/*******************************************************************************
*@ Module    	  	:  Clear interrupt status 
*@ Description    :  NULL
*******************************************************************************/
void Hal_I2C_Slave_CLR_IRQs(uint8_t handle,uint32_t irqs)
{
	Hal_INTR_SOURCE_Clear(Slave_cfg_g[handle].addr,irqs);
}

/*******************************************************************************
*@ Module    	  	:  Hal_I2C_Slave_WriteTX_FIFO 
*@ Description    :  NULL
*******************************************************************************/
void Hal_I2C_Slave_WriteTX_FIFO(uint8_t handle,uint8_t *p,uint8_t len)
{
	for(uint8_t i=0;i<len;i++)
		Hal_IIC_Write_TXFIFO(Slave_cfg_g[handle].addr,*p++);
}

/*******************************************************************************
*@ Module    	  	:  I2C Slave Init steps:
*@ Description    :  NULL
*******************************************************************************/
/*
	1、IC_ENABLE=0;
	2、IC_SAR = ? （Master和Slave不能设置相同的地址类型？）
	3、IC_CON(配置地址模式和SLAVE模式)
	4、IC_ENABLE=1;
*/
/*******************************************************************************
*@ Module			:  I2C Slave 单字节发�?
*@ Description	  :  NULL
*******************************************************************************/
/*
	1、IIC MASTER 寻址
	2、IIC SLAVE ACK
	3、IIC SLAVE 触发 RD_REQ 中断�?同时 HOLD THE SCL LOW , WAIT UNTIL THE SOFTWARE RESPONDS(数据响应�?
		SOFTWARE RESPONDS的时间间隔，10倍SCL周期 �?00K--->25us）（一个byte传输完成的时间）
	4、读请求触发前，如果TXFIFO,总线触发TX_ABRT中断，清除旧数据	（通过软件读取 IC_CLR_TX_ABRT register，释放总线�?
	5、写数据�?IC_DATA_CMD
	6、清除RD_REQ,TX_ABRT中断标志位（如果中断被屏蔽，则需要清除IC_RAW_INTR_STAT�?
	7、总线释放SCL并传输数据（�?对应�?
	8、MASTER 通过RESTART �?STOP 继续操作总线
*/
/*******************************************************************************
*@ Module			:  I2C Slave 单字节接�?
*@ Description	  :  NULL
*******************************************************************************/
/*
	1、IIC MASTER 寻址
	2、IIC SLAVE ACK
	3、receives the transmitted byte and places it in the receive buffer
		如果RX FIFO已经满了，再来数据的时候，将会触发R_RX_OVER中断，于此同时，
		IIC数据将会继续传输（没有NACK信号），并无法保证后续数据的完整
	4、RX_FULL 中断
	5、从IC_DATA_CMD 中读取数�?
	6、MASTER 通过RESTART �?STOP 继续操作总线
*/

